import { isWindows } from '@ohos/hvigor';

import { TaskStatus } from '../project-builder/models/constants';

type ExecaResult = {
  stdout: string;
  stderr: string;
}

export interface ICaseRecord {

  /**
   * 用例报告输出文件夹根路径
   *
   * @type {string}
   */
  rootPath?: string;

  /**
   * 记录执行结果
   */
  results: [string, ExecaResult][];

  /**
   * 用例名称
   *
   * @type {string}
   */
  readonly caseName: string;

  /**
   * 任务描述
   *
   * @type {string}
   */
  description?: string;

  /**
   * 任务状态
   *
   * @type {TaskStatus}
   */
  taskStatus: TaskStatus;

  /**
   * 异常信息
   *
   * @type {string}
   */
  errorMessage?: string;

  /**
   * 开始时间
   *
   * @type {Date}
   */
  startTime?: Date;

  /**
   * 结束时间
   *
   * @type {Date}
   */
  endTime?: Date;

  /**
   * 工程文件路径
   * @type {string}
   */
  projectPath?: string;

  /**
   * 输出日志路径
   * @type {string}
   */
  consoleLogPath?: string;

  /**
   * 错误日志路径
   * @type {string}
   */
  errorLogPath?: string;

  /**
   * 报告文件路径
   *
   * @type {string}
   */
  reportPath?: string;

  /**
   * 添加测试步骤记录
   *
   * @param {string} stepName
   * @param {ExecaResult} executeResult
   */
  addStep(stepName: string, executeResult: ExecaResult): void;
}

/**
 * 单条测试用例的执行记录
 */
class CaseRecord implements ICaseRecord {

  /**
   * 用例报告输出文件夹根路径
   *
   * @type {string}
   */
  rootPath?: string;

  /**
   * 记录执行结果
   */
  readonly results: [string, ExecaResult][] = [];

  /**
   * 用例名称
   *
   * @type {string}
   */
  readonly caseName: string;

  /**
   * 任务描述
   *
   * @type {string}
   */
  description?: string;

  /**
   * 任务状态
   *
   * @type {TaskStatus}
   */
  taskStatus: TaskStatus = TaskStatus.NotExecuted;

  /**
   * 异常信息
   *
   * @type {string}
   */
  errorMessage?: string;

  /**
   * 开始时间
   *
   * @type {Date}
   */
  startTime?: Date;

  /**
   * 结束时间
   *
   * @type {Date}
   */
  endTime?: Date;

  /**
   * 工程文件路径
   * @type {string}
   */
  projectPath?: string;

  /**
   * 输出日志路径
   * @type {string}
   */
  consoleLogPath?: string;

  /**
   * 错误日志路径
   * @type {string}
   */
  errorLogPath?: string;

  /**
   * 报告文件路径
   *
   * @type {string}
   */
  reportPath?: string;

  constructor(caseName: string) {
    this.caseName = caseName;
  }

  /**
   * 添加测试步骤记录
   *
   * @param {string} stepName
   * @param {ExecaResult} executeResult
   */
  addStep(stepName: string, executeResult: ExecaResult): void {
    this.results.push([stepName, executeResult]);
  }
}

export interface ITaskReport {

  /**
   * 是否是windows环境
   */
  isWindows: boolean;

  /**
   * 报告输出文件夹根路径
   *
   * @type {string}
   */
  rootPath?: string;

  /**
   * 测试用例记录对象集合
   *
   * @type {{[p: string]: CaseRecord}}
   */
  records: { [key: string]: CaseRecord; };

  /**
   * 总体任务数
   *
   * @type {number}
   */
  allTask: number;

  /**
   * 执行通过任务数
   *
   * @type {number}
   */
  passTask: number;

  /**
   * 执行失败任务数
   *
   * @type {number}
   */
  failedTask: number;

  /**
   * 未执行任务数
   *
   * @type {number}
   */
  noRunTask: number;

  /**
   * 开始时间
   *
   * @type {Date}
   */
  startTime?: Date;

  /**
   * 结束时间
   *
   * @type {Date}
   */
  endTime?: Date;

  /**
   * 报告文件路径
   *
   * @type {string}
   */
  reportPath?: string;
}

/**
 * 测试任务总体报告
 */
class TaskReport implements ITaskReport {

  /**
   * 是否是windows环境
   *
   * @type {boolean}
   */
  isWindows: boolean;

  /**
   * 报告输出文件夹根路径
   *
   * @type {string}
   */
  rootPath?: string;

  /**
   * 测试用例记录对象集合
   *
   * @type {{[p: string]: CaseRecord}}
   */
  records: { [key: string]: CaseRecord; } = {};

  /**
   * 总体任务数
   *
   * @type {number}
   */
  allTask = 0;

  /**
   * 执行通过任务数
   *
   * @type {number}
   */
  passTask = 0;

  /**
   * 执行失败任务数
   *
   * @type {number}
   */
  failedTask = 0;

  /**
   * 未执行任务数
   *
   * @type {number}
   */
  noRunTask = 0;

  /**
   * 开始时间
   *
   * @type {Date}
   */
  startTime?: Date;

  /**
   * 结束时间
   *
   * @type {Date}
   */
  endTime?: Date;

  /**
   * 报告文件路径
   *
   * @type {string}
   */
  reportPath?: string;

  constructor() {
    this.isWindows = isWindows();
  }

  /**
   * 获取单个用例的记录
   *
   * @param {string} caseName
   * @return {CaseRecord}
   */
  public caseRecord(caseName: string): CaseRecord {
    let record = this.records[caseName];
    if (record === undefined) {
      record = new CaseRecord(caseName);
      this.records[caseName] = record;
    }

    return record;
  }
}

export const taskReport = new TaskReport();
